﻿using System;
using Microsoft.Xna.Framework;

namespace lumo.input
{
    /// <summary>
    /// A simple axis using 2 Triggers
    /// </summary>
    public class Axis : IAxis
    {
        /// <summary>
        /// The XAxis
        /// </summary>
        public ITrigger PositiveTrigger;

        /// <summary>
        /// The YAxis
        /// </summary>
        public ITrigger NegativeTrigger;

        private bool LastDown;
        private bool CurrentDown;
        private float RepeatCount = 0;
        private float _RepeatDelay = Config.DefaultRepeatDelay;
        private float _RepeatTime = Config.DefaultRepeatTime;
        private float _Value = 0;

        // The propertie for frame ID
        private uint _FrameID = 0;
        /// <summary>Access for FrameID</summary>
        public uint FrameID { get { return _FrameID; } }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="PositiveTrigger">The PositiveTrigger</param>
        /// <param name="NegativeTrigger">The NegativeTrigger</param>
        public Axis(ITrigger PositiveTrigger, ITrigger NegativeTrigger)
        {
            this.PositiveTrigger = PositiveTrigger;
            this.NegativeTrigger = NegativeTrigger;
            this._Value           = MathHelper.Clamp(this.PositiveTrigger.Value - this.NegativeTrigger.Value, -1, 1);
            this.Reverse        = false;
            Repeated = false;
        }

        /// <summary>
        /// The value
        /// </summary>
        public float Value { get { return (this.Reverse ? -_Value : _Value); } }


        /// <summary>
        /// The value
        /// </summary>
        public bool Reverse { get; set; }

        /// <summary>
        /// Update the key.
        /// </summary>
        /// <param name="Game">The game object</param>
        public void Update(LumoComponent Game)
        {
            // Only called once per frame.
            if (_FrameID == Game.FrameID)
                return;
            _FrameID = Game.FrameID;

            this.PositiveTrigger.Update(Game);
            this.NegativeTrigger.Update(Game);

            this._Value = MathHelper.Clamp(this.PositiveTrigger.Value - this.NegativeTrigger.Value, -1, 1);
            LastDown = CurrentDown;
            CurrentDown = (Math.Abs(this.Value) >= 0.5);
            Repeated = false;
            if (Game == null)
            {
                Repeated = Triggered;
                return;
            }

            if (CurrentDown)
            {
                if (!LastDown)
                {
                    Repeated = true;
                    RepeatCount = _RepeatDelay;
                }
                else
                {
                    RepeatCount -= (float)Game.GameTime.ElapsedGameTime.TotalMilliseconds;
                    if (RepeatCount <= 0)
                    {
                        Repeated = true;
                        RepeatCount = _RepeatTime;
                    }
                }
            }
        }

        /// <summary>
        /// Type of object.
        /// </summary>
        /// <returns>The type of object.</returns>
        public InputType GetInputType() { return InputType.Axis; }

        /// <summary>
        /// Return the Button.
        /// </summary>
        /// <returns>The ID.</returns>
        public long GetInputID() { return 0; }

        /// <summary>
        /// Property to check if key is pressed.
        /// </summary>
        public bool Pressed { get { return CurrentDown; } }

        /// <summary>
        /// Property to check if key is triggered.
        /// </summary>
        public bool Triggered { get { return (CurrentDown && !LastDown); } }

        /// <summary>
        /// Property to check if key is repeated.
        /// </summary>
        public bool Repeated { get; private set; }

        /// <summary>
        /// Property to check if key is released.
        /// </summary>
        public bool Released { get { return (LastDown && !CurrentDown); } }

        /// <summary>
        /// Implemented IInputObject Released.
        /// </summary>
        /// <returns>True if the key is released.</returns>
        public float RepeatDelay { get { return _RepeatDelay; } set { _RepeatDelay = value; } }

        /// <summary>
        /// Implemented IInputObject Released.
        /// </summary>
        /// <returns>True if the key is released.</returns>
        public float RepeatTime { get { return _RepeatTime; } set { _RepeatTime = value; } }
    }
}
